package skeleton;
import java.io.*;
import java.net.*;

import javax.swing.SwingUtilities;

import util.Config;
import util.Lib;

public class Startup {
	static final int COMM_MSG_DONOTHING = 0; //do nothing, ignore it!
	static final int COMM_MSG_REJECTED = 1; //last request is rejected
	static final int COMM_MSG_ACCEPT = 2; //last request is accepted
	static final int COMM_MSG_FIRST = 3; //go first when the game starts
	static final int COMM_MSG_SECOND = 4; //go second when the game starts
	static final int COMM_MSG_GAME_REQUIRE_START = 5; //request for game start
	static final int COMM_MSG_GAME_START = 6; //game start
	static final int COMM_MSG_CHESS = 7; //information for chess
	static final int COMM_MSG_TIMEOUT = 8; //time out when one peer takes too many time in a bout
	static final int COMM_MSG_WIN = 9; //win
	static final int COMM_MSG_LOSE = 10; //lose
	static final int COMM_MSG_DRAW = 11; //draw	
	public static final int Chess_Clr_Black = 0;
	public static final int Chess_Clr_White = 1;

	static final int UNSTART = 0;
	static final int SEND_FIRST = 1;
	static final int SEND_SECOND = 2;
	static final int FIRST = 3;
	static final int SECOND = 4;
	static final int WAIT_TURN = 5;
	static final int SEND_MY_CHESS = 6;
	
	static Socket socket;
	static InputStream in;
	static OutputStream out;
	static int state = UNSTART, serverInfo;
	static Player player;
	static int mode = -1;

	public static void main(String[] args) {
		Config.load("config.txt");
		player = new Player();
		mode = Config.getInteger("Mode");
		if (mode == 0)
			comVsCom();
		else if (mode == 1)
			humVsCom();
		else if (mode == 2)
			comVsHum();
		else if (mode == 3)
			humVsHum();
		else
			System.err.println("error mode.");
	}

	private static void humVsHum() {
	}
	
	private static void comVsHum() {
		player.setColor((byte) Chess_Clr_Black);
		player.putChess();
	}
	
	private static void humVsCom() {
		player.setColor((byte) Chess_Clr_White);
	}
	
	private static void comVsCom() {
		println(Config.getString("ServerIP"));
		try
		{
			socket = new Socket(Config.getString("ServerIP"), 9527);
			in = socket.getInputStream();
//			in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			out = socket.getOutputStream();
			while (serverInfo != -1) {
				serverInfo = in.read();
				println(serverInfo);
				doAction();
				out.flush();
			}

			out.close();
			in.close();
			socket.close();
		}
		catch (IOException e){
			e.printStackTrace();
		}
	}
	
	public static void doAction() {
		switch (serverInfo) {
			case COMM_MSG_FIRST: 
				if (state == UNSTART) {
					try {
						out.write((byte)COMM_MSG_FIRST);
					} catch (IOException e) {
						e.printStackTrace();
					}
					state = SEND_FIRST;
				}
				break;
			case COMM_MSG_SECOND:
				if (state == UNSTART) {
					try {
						out.write((byte)COMM_MSG_SECOND);
					} catch (IOException e) {
						e.printStackTrace();
					} 
					state = SEND_SECOND;
				}
				break;
			case COMM_MSG_ACCEPT: {
				switch (state) {
					case SEND_FIRST:
						state = FIRST;
						break;
					case SEND_SECOND:
						state = SECOND;
					try {
						out.write((byte)COMM_MSG_GAME_REQUIRE_START);
					} catch (IOException e) {
						e.printStackTrace();
					}
						break;
					case SEND_MY_CHESS:
						state = WAIT_TURN;
						break;
				}
				break;
			}
			case COMM_MSG_GAME_START:
				player.setColor((byte) ((state == FIRST)?Chess_Clr_Black:Chess_Clr_White));
				if (state == FIRST) {
					ChessInfo info = player.putChess();
					try {
						out.write(formatChessInfo(info));
					} catch (IOException e) {
						e.printStackTrace();
					}
					state = SEND_MY_CHESS;
				}
				else {
					state = WAIT_TURN;
				}
				break;
			case COMM_MSG_CHESS:
				Lib.assertTrue(state == WAIT_TURN);
				ChessInfo info = readChessInfo();
				if (info.color != player.getColor()) {
					player.updateBoard(info);
					info = player.putChess();
					try {
						out.write(formatChessInfo(info));
					} catch (IOException e) {
						e.printStackTrace();
					}
					state = SEND_MY_CHESS;
				}
				else
					println("none of my business.");
				break;
			case COMM_MSG_REJECTED:
				byte[] cbuf = new byte[4];
				try {
					in.read(cbuf, 0, 4);
				} catch (IOException e) {
					e.printStackTrace();
				}
				System.err.println("message rejected!!!current state is: " + state);
				System.err.println("reject information :");
				System.err.println("	reason: " + 
						((cbuf[0]==1)?"unwanted":"invalid chess"));
				System.err.println("	solution: " + 
						((cbuf[1]==0)?"no action":"action repeat"));
				String errmsg = "";
				switch (cbuf[2]) {
					case 0: errmsg = "do nothing"; break;
					case 3: errmsg = "first"; break;
					case 4: errmsg = "second"; break;
					case 5: errmsg = "game require start"; break;
					case 7: errmsg = "chess"; break;
				}
				System.err.println("	parameter: " + errmsg);
				break;
			case COMM_MSG_WIN:
			case COMM_MSG_DRAW:
			case COMM_MSG_LOSE:
				System.out.println("game over.");
			try {
				System.in.read();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
				System.exit(0);
		}
	}
	
	static byte[] formatChessInfo(ChessInfo info) {
		byte[] array = new byte[9];
		array[0] = COMM_MSG_CHESS;
		array[1] = info.index;
		array[2] = info.color;
		array[3] = info.row;
		array[4] = info.col;
		return array;
	}
	
	static ChessInfo readChessInfo() {
		byte[] cbuf = new byte[8];
		try {
			in.read(cbuf, 0, 8);
		} catch (IOException e) {
			e.printStackTrace();
		}
		System.out.println();
		ChessInfo info  = new ChessInfo();
		info.color = cbuf[1];
		info.row = cbuf[2];
		info.col = cbuf[3];
		return info;
	}
	
	public static void println(Object o) {
		System.out.println(o);
	}
}
